﻿
// CV_ClassOneView.cpp: CCVClassOneView 类的实现
//

#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "CV_ClassOne.h"
#endif

#include "CV_ClassOneDoc.h"
#include "CV_ClassOneView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CCVClassOneView

IMPLEMENT_DYNCREATE(CCVClassOneView, CView)

BEGIN_MESSAGE_MAP(CCVClassOneView, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_TIMER()
	ON_WM_LBUTTONDBLCLK()
END_MESSAGE_MAP()

// CCVClassOneView 构造/析构

/*
	Modify
*/
CCVClassOneView::CCVClassOneView() noexcept
{
	int R = GetSystemMetrics(SM_CXFULLSCREEN) / 20;		// 将小球半径设置为 最大化窗体的显示区域宽度的 1/20
	sphere.SetParameter(R, CPoint(200, 100));			// 将小球的起始点设置为（200，100）

	distance = CPoint(1, 1);							// 将小球x、y方向的移动距离都定为1
	displaying = false;									// 初始化未播放状态
}

CCVClassOneView::~CCVClassOneView()
{
}

BOOL CCVClassOneView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// CCVClassOneView 绘图

/*
	New
*/
void CCVClassOneView::DoubleBuffer(CDC* pDC)
{
	// 获取当前窗口客户区（即图片中的黑色区域）的大小
	CRect rect;
	GetClientRect(&rect);

	// 创建一个与显示DC相兼容的内存DC
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);	
	
	CBitmap newBitMap, *oldBitMap;
	newBitMap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());		// 创建兼容内存位图，用以存储更新后的图像
	oldBitMap = memDC.SelectObject(&newBitMap);								// 将新位图放进内存DC中，并返回旧位图

	sphere.Draw(&memDC);													// 绘制新位图，并存到内存DC中

	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);	// 将内存DC的位图复制到显示DC用以显示在屏幕上

	memDC.SelectObject(oldBitMap);											// 将旧位图归还给内存DC
	newBitMap.DeleteObject();												// 释放新位图资源
	memDC.DeleteDC();														// 释放内存DC
}

/*
	New
*/
void CCVClassOneView::CollisionDetection()
{
	// 获取当前窗口客户区（即图片中的黑色区域）的大小
	CRect rect;
	GetClientRect(&rect);

	// 获取当前小球位置信息
	CPoint centerPoint = sphere.GetCenterPoint();
	int radius = sphere.GetRadius();

	// 根据小球边缘坐标与窗口大小位置，更新移动距离
	// 注意：在窗口中，左顶点为原点，从左到右为X轴正方向，从上到下是Y轴正方向
	if (centerPoint.x - radius < 0)
		distance.x = 1;
	if (centerPoint.x + radius > rect.Width())
		distance.x = -1;
	if (centerPoint.y - radius < 0)
		distance.y = 1;
	if (centerPoint.y + radius > rect.Height())
		distance.y = -1;
		
}

/*
	Modify
*/
void CCVClassOneView::OnDraw(CDC* pDC)
{
	CCVClassOneDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// 使用双缓冲绘图算法
	DoubleBuffer(pDC);
}


// CCVClassOneView 打印

BOOL CCVClassOneView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CCVClassOneView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CCVClassOneView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// CCVClassOneView 诊断

#ifdef _DEBUG
void CCVClassOneView::AssertValid() const
{
	CView::AssertValid();
}

void CCVClassOneView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CCVClassOneDoc* CCVClassOneView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCVClassOneDoc)));
	return (CCVClassOneDoc*)m_pDocument;
}
#endif //_DEBUG


// CCVClassOneView 消息处理程序

/*
	New
*/
void CCVClassOneView::OnTimer(UINT_PTR nIDEvent)
{
	CollisionDetection();				// 检测小球当前位置是否发生碰撞，然后更新相应移动距离
	sphere.MoveCenterPoint(distance);	// 更新小球位置
	Invalidate(FALSE);					// 调用OnDraw()函数

	CView::OnTimer(nIDEvent);
}

/*
	New
*/
void CCVClassOneView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	displaying = !displaying;	// 鼠标左键双击，即改变播放状态

	if (displaying)
		SetTimer(1, 10, NULL);	// 如果 displaying = true， 则设置定时器开始更新小球位置，进而显示出小球的运动
	else
		KillTimer(1);			// 如果 displaying = false，则关闭该定时器，小球不再运动

	CView::OnLButtonDblClk(nFlags, point);
}
